package com.yxsk.relay.job.admin.core.log;

import com.alibaba.fastjson.TypeReference;
import com.yxsk.relay.job.admin.core.remote.RemoteCallerSelector;
import com.yxsk.relay.job.component.common.constant.NetProtocol;
import com.yxsk.relay.job.component.common.constant.UriConstant;
import com.yxsk.relay.job.component.common.exception.RelayJobRuntimeException;
import com.yxsk.relay.job.component.common.exception.remote.RemoteCallException;
import com.yxsk.relay.job.component.common.protocol.caller.RemoteCaller;
import com.yxsk.relay.job.component.common.protocol.message.BaseRequest;
import com.yxsk.relay.job.component.common.protocol.message.base.ResultResponse;
import com.yxsk.relay.job.component.common.protocol.message.log.delete.LogDeleteRequestDto;
import com.yxsk.relay.job.component.common.protocol.message.log.delete.LogDeleteResponseDto;
import com.yxsk.relay.job.component.common.protocol.message.log.query.LogQueryRequestDto;
import com.yxsk.relay.job.component.common.protocol.message.log.query.LogQueryResponseDto;
import com.yxsk.relay.job.component.common.utils.DateUtils;
import com.yxsk.relay.job.component.common.utils.SerialNoUtils;
import com.yxsk.relay.job.component.common.vo.Endpoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author 11376
 * @CreaTime 2019/8/10 17:00
 * @Description
 */
@Component
public class EndpointLogService {

    @Autowired
    private RemoteCallerSelector callerSelector;

    public List<String> loadLog(Endpoint endpoint, String logId, Long startLine, Long endLine) throws RemoteCallException {
        Assert.notNull(endpoint, "Load log endpoint not be null");
        Assert.hasLength(logId, "Query log of logId not be empty");

        // 组装请求报文
        LogQueryRequestDto requestDto = new LogQueryRequestDto();
        requestDto.setSerialNo(SerialNoUtils.nextId());
        requestDto.setVersion(UriConstant.VERSION_NO);
        requestDto.setRequestTime(DateUtils.getCurrentDate());

        requestDto.setLogId(logId);
        requestDto.setStartLine(startLine);
        requestDto.setEndLine(endLine);

        // 请求
        ResultResponse<LogQueryResponseDto> resultResponse = this.remoteCall(endpoint.getProtocol(), endpoint.getHost(), endpoint.getPort(),
                UriConstant.LOG_QUERY, endpoint.getAuthToken(), requestDto, new TypeReference<ResultResponse<LogQueryResponseDto>>() {
                });

        if (ResultResponse.isOk(resultResponse)) {
            return resultResponse.getData().getLogs();
        }
        throw new RelayJobRuntimeException(resultResponse.getMessage());
    }

    public void deleteLog(Endpoint endpoint, String logId) throws RemoteCallException {
        Assert.notNull(endpoint, "Load log endpoint not be null");
        LogDeleteRequestDto requestDto = new LogDeleteRequestDto();
        requestDto.setSerialNo(SerialNoUtils.nextId());
        requestDto.setRequestTime(DateUtils.getCurrentDate());
        requestDto.setVersion(UriConstant.VERSION_NO);

        requestDto.setLogId(logId);

        // 远程删除
        ResultResponse<LogDeleteResponseDto> resultResponse = this.remoteCall(endpoint.getProtocol(), endpoint.getHost(), endpoint.getPort(),
                UriConstant.LOG_DELETE, endpoint.getAuthToken(), requestDto, new TypeReference<ResultResponse<LogDeleteResponseDto>>() {
                });

        if (!ResultResponse.isOk(resultResponse)) {
            throw new RelayJobRuntimeException(resultResponse.getMessage());
        }
    }


    private <T> T remoteCall(NetProtocol netProtocol, String host, Integer port,
                             String uri, String authToken, BaseRequest request, TypeReference<T> reference) throws RemoteCallException {
        Assert.notNull(netProtocol, "Net protocol net be null");
        Assert.hasLength(uri, "Request uri not be empty");

        Map<String, String> header = null;
        if (StringUtils.hasLength(authToken)) {
            header = new HashMap<>(2);
            header.put(UriConstant.AUTHORIZATION_HEADER_KEY, authToken);
        }

        RemoteCaller caller = this.callerSelector.select(netProtocol);

        String requestURL = caller.buildUri(host, port, uri);

        return caller.call(request, header, requestURL, reference);
    }

}
